/* do not edit automatically generated by mc from NumberIO.  */
/* NumberIO.mod provides conversion of ordinal numbers.

Copyright (C) 2001-2023 Free Software Foundation, Inc.
Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>.

This file is part of GNU Modula-2.

GNU Modula-2 is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.

GNU Modula-2 is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

Under Section 7 of GPL version 3, you are granted additional
permissions described in the GCC Runtime Library Exception, version
3.1, as published by the Free Software Foundation.

You should have received a copy of the GNU General Public License and
a copy of the GCC Runtime Library Exception along with this program;
see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
<http://www.gnu.org/licenses/>.  */

#include "config.h"
#include "system.h"
#include <stdbool.h>
#   if !defined (PROC_D)
#      define PROC_D
       typedef void (*PROC_t) (void);
       typedef struct { PROC_t proc; } PROC;
#   endif

#   if !defined (TRUE)
#      define TRUE (1==1)
#   endif

#   if !defined (FALSE)
#      define FALSE (1==0)
#   endif

#define _NumberIO_H
#define _NumberIO_C

#   include "GASCII.h"
#   include "GStrIO.h"
#   include "GStrLib.h"
#   include "GM2RTS.h"

#   define MaxLineLength 79
#   define MaxDigits 20
#   define MaxHexDigits 20
#   define MaxOctDigits 40
#   define MaxBits 64
extern "C" void NumberIO_ReadCard (unsigned int *x);
extern "C" void NumberIO_WriteCard (unsigned int x, unsigned int n);
extern "C" void NumberIO_ReadHex (unsigned int *x);
extern "C" void NumberIO_WriteHex (unsigned int x, unsigned int n);
extern "C" void NumberIO_ReadInt (int *x);
extern "C" void NumberIO_WriteInt (int x, unsigned int n);
extern "C" void NumberIO_CardToStr (unsigned int x, unsigned int n, char *a, unsigned int _a_high);
extern "C" void NumberIO_StrToCard (const char *a_, unsigned int _a_high, unsigned int *x);
extern "C" void NumberIO_HexToStr (unsigned int x, unsigned int n, char *a, unsigned int _a_high);
extern "C" void NumberIO_StrToHex (const char *a_, unsigned int _a_high, unsigned int *x);
extern "C" void NumberIO_IntToStr (int x, unsigned int n, char *a, unsigned int _a_high);
extern "C" void NumberIO_StrToInt (const char *a_, unsigned int _a_high, int *x);
extern "C" void NumberIO_ReadOct (unsigned int *x);
extern "C" void NumberIO_WriteOct (unsigned int x, unsigned int n);
extern "C" void NumberIO_OctToStr (unsigned int x, unsigned int n, char *a, unsigned int _a_high);
extern "C" void NumberIO_StrToOct (const char *a_, unsigned int _a_high, unsigned int *x);
extern "C" void NumberIO_ReadBin (unsigned int *x);
extern "C" void NumberIO_WriteBin (unsigned int x, unsigned int n);
extern "C" void NumberIO_BinToStr (unsigned int x, unsigned int n, char *a, unsigned int _a_high);
extern "C" void NumberIO_StrToBin (const char *a_, unsigned int _a_high, unsigned int *x);
extern "C" void NumberIO_StrToBinInt (const char *a_, unsigned int _a_high, int *x);
extern "C" void NumberIO_StrToHexInt (const char *a_, unsigned int _a_high, int *x);
extern "C" void NumberIO_StrToOctInt (const char *a_, unsigned int _a_high, int *x);

extern "C" void NumberIO_ReadCard (unsigned int *x)
{
  typedef struct ReadCard__T1_a ReadCard__T1;

  struct ReadCard__T1_a { char array[MaxLineLength+1]; };
  ReadCard__T1 a;

  StrIO_ReadString ((char *) &a.array[0], MaxLineLength);
  NumberIO_StrToCard ((const char *) &a.array[0], MaxLineLength, x);
}

extern "C" void NumberIO_WriteCard (unsigned int x, unsigned int n)
{
  typedef struct WriteCard__T2_a WriteCard__T2;

  struct WriteCard__T2_a { char array[MaxLineLength+1]; };
  WriteCard__T2 a;

  NumberIO_CardToStr (x, n, (char *) &a.array[0], MaxLineLength);
  StrIO_WriteString ((const char *) &a.array[0], MaxLineLength);
}

extern "C" void NumberIO_ReadHex (unsigned int *x)
{
  typedef struct ReadHex__T3_a ReadHex__T3;

  struct ReadHex__T3_a { char array[MaxLineLength+1]; };
  ReadHex__T3 a;

  StrIO_ReadString ((char *) &a.array[0], MaxLineLength);
  NumberIO_StrToHex ((const char *) &a.array[0], MaxLineLength, x);
}

extern "C" void NumberIO_WriteHex (unsigned int x, unsigned int n)
{
  typedef struct WriteHex__T4_a WriteHex__T4;

  struct WriteHex__T4_a { char array[MaxLineLength+1]; };
  WriteHex__T4 a;

  NumberIO_HexToStr (x, n, (char *) &a.array[0], MaxLineLength);
  StrIO_WriteString ((const char *) &a.array[0], MaxLineLength);
}

extern "C" void NumberIO_ReadInt (int *x)
{
  typedef struct ReadInt__T5_a ReadInt__T5;

  struct ReadInt__T5_a { char array[MaxLineLength+1]; };
  ReadInt__T5 a;

  StrIO_ReadString ((char *) &a.array[0], MaxLineLength);
  NumberIO_StrToInt ((const char *) &a.array[0], MaxLineLength, x);
}

extern "C" void NumberIO_WriteInt (int x, unsigned int n)
{
  typedef struct WriteInt__T6_a WriteInt__T6;

  struct WriteInt__T6_a { char array[MaxLineLength+1]; };
  WriteInt__T6 a;

  NumberIO_IntToStr (x, n, (char *) &a.array[0], MaxLineLength);
  StrIO_WriteString ((const char *) &a.array[0], MaxLineLength);
}

extern "C" void NumberIO_CardToStr (unsigned int x, unsigned int n, char *a, unsigned int _a_high)
{
  typedef struct CardToStr__T7_a CardToStr__T7;

  struct CardToStr__T7_a { unsigned int array[MaxDigits-1+1]; };
  unsigned int i;
  unsigned int j;
  unsigned int Higha;
  CardToStr__T7 buf;

  i = 0;
  do {
    i += 1;
    if (i > MaxDigits)
      {
        StrIO_WriteString ((const char *) "NumberIO - increase MaxDigits", 29);
        StrIO_WriteLn ();
        M2RTS_HALT (-1);
        __builtin_unreachable ();
      }
    buf.array[i-1] = x % 10;
    x = x / 10;
  } while (! (x == 0));
  j = 0;
  Higha = _a_high;
  while ((n > i) && (j <= Higha))
    {
      a[j] = ' ';
      j += 1;
      n -= 1;
    }
  while ((i > 0) && (j <= Higha))
    {
      a[j] = ((char) (buf.array[i-1]+ ((unsigned int) ('0'))));
      j += 1;
      i -= 1;
    }
  if (j <= Higha)
    {
      a[j] = ASCII_nul;
    }
}

extern "C" void NumberIO_StrToCard (const char *a_, unsigned int _a_high, unsigned int *x)
{
  unsigned int i;
  bool ok;
  unsigned int higha;
  char a[_a_high+1];

  /* make a local copy of each unbounded array.  */
  memcpy (a, a_, _a_high+1);

  StrLib_StrRemoveWhitePrefix ((const char *) a, _a_high, (char *) a, _a_high);
  higha = StrLib_StrLen ((const char *) a, _a_high);
  i = 0;
  ok = true;
  while (ok)
    {
      if (i < higha)
        {
          if ((a[i] < '0') || (a[i] > '9'))
            {
              i += 1;
            }
          else
            {
              ok = false;
            }
        }
      else
        {
          ok = false;
        }
    }
  (*x) = 0;
  if (i < higha)
    {
      ok = true;
      do {
        (*x) = (10*(*x))+( ((unsigned int) (a[i]))- ((unsigned int) ('0')));
        if (i < higha)
          {
            /* avoid dangling else.  */
            i += 1;
            if ((a[i] < '0') || (a[i] > '9'))
              {
                ok = false;
              }
          }
        else
          {
            ok = false;
          }
      } while (! (! ok));
    }
}

extern "C" void NumberIO_HexToStr (unsigned int x, unsigned int n, char *a, unsigned int _a_high)
{
  typedef struct HexToStr__T8_a HexToStr__T8;

  struct HexToStr__T8_a { unsigned int array[MaxHexDigits-1+1]; };
  unsigned int i;
  unsigned int j;
  unsigned int Higha;
  HexToStr__T8 buf;

  i = 0;
  do {
    i += 1;
    if (i > MaxHexDigits)
      {
        StrIO_WriteString ((const char *) "NumberIO - increase MaxDigits", 29);
        StrIO_WriteLn ();
        M2RTS_HALT (-1);
        __builtin_unreachable ();
      }
    buf.array[i-1] = x % 0x010;
    x = x / 0x010;
  } while (! (x == 0));
  j = 0;
  Higha = _a_high;
  while ((n > i) && (j <= Higha))
    {
      a[j] = '0';
      j += 1;
      n -= 1;
    }
  while ((i != 0) && (j <= Higha))
    {
      if (buf.array[i-1] < 10)
        {
          a[j] = ((char) (buf.array[i-1]+ ((unsigned int) ('0'))));
        }
      else
        {
          a[j] = ((char) ((buf.array[i-1]+ ((unsigned int) ('A')))-10));
        }
      j += 1;
      i -= 1;
    }
  if (j <= Higha)
    {
      a[j] = ASCII_nul;
    }
}

extern "C" void NumberIO_StrToHex (const char *a_, unsigned int _a_high, unsigned int *x)
{
  int i;
  char a[_a_high+1];

  /* make a local copy of each unbounded array.  */
  memcpy (a, a_, _a_high+1);

  NumberIO_StrToHexInt ((const char *) a, _a_high, &i);
  (*x) = (unsigned int ) (i);
}

extern "C" void NumberIO_IntToStr (int x, unsigned int n, char *a, unsigned int _a_high)
{
  typedef struct IntToStr__T9_a IntToStr__T9;

  struct IntToStr__T9_a { unsigned int array[MaxDigits-1+1]; };
  unsigned int i;
  unsigned int j;
  unsigned int c;
  unsigned int Higha;
  IntToStr__T9 buf;
  bool Negative;

  if (x < 0)
    {
      /* avoid dangling else.  */
      Negative = true;
      c = ((unsigned int ) (abs (x+1)))+1;
      if (n > 0)
        {
          n -= 1;
        }
    }
  else
    {
      c = x;
      Negative = false;
    }
  i = 0;
  do {
    i += 1;
    if (i > MaxDigits)
      {
        StrIO_WriteString ((const char *) "NumberIO - increase MaxDigits", 29);
        StrIO_WriteLn ();
        M2RTS_HALT (-1);
        __builtin_unreachable ();
      }
    buf.array[i-1] = c % 10;
    c = c / 10;
  } while (! (c == 0));
  j = 0;
  Higha = _a_high;
  while ((n > i) && (j <= Higha))
    {
      a[j] = ' ';
      j += 1;
      n -= 1;
    }
  if (Negative)
    {
      a[j] = '-';
      j += 1;
    }
  while ((i != 0) && (j <= Higha))
    {
      a[j] = ((char) (buf.array[i-1]+ ((unsigned int) ('0'))));
      j += 1;
      i -= 1;
    }
  if (j <= Higha)
    {
      a[j] = ASCII_nul;
    }
}

extern "C" void NumberIO_StrToInt (const char *a_, unsigned int _a_high, int *x)
{
  unsigned int i;
  bool ok;
  bool Negative;
  unsigned int higha;
  char a[_a_high+1];

  /* make a local copy of each unbounded array.  */
  memcpy (a, a_, _a_high+1);

  StrLib_StrRemoveWhitePrefix ((const char *) a, _a_high, (char *) a, _a_high);
  higha = StrLib_StrLen ((const char *) a, _a_high);
  i = 0;
  Negative = false;
  ok = true;
  while (ok)
    {
      if (i < higha)
        {
          if (a[i] == '-')
            {
              i += 1;
              Negative = ! Negative;
            }
          else if ((a[i] < '0') || (a[i] > '9'))
            {
              /* avoid dangling else.  */
              i += 1;
            }
          else
            {
              /* avoid dangling else.  */
              ok = false;
            }
        }
      else
        {
          ok = false;
        }
    }
  (*x) = 0;
  if (i < higha)
    {
      ok = true;
      do {
        if (Negative)
          {
            (*x) = (10*(*x))-((int ) ( ((unsigned int) (a[i]))- ((unsigned int) ('0'))));
          }
        else
          {
            (*x) = (10*(*x))+((int ) ( ((unsigned int) (a[i]))- ((unsigned int) ('0'))));
          }
        if (i < higha)
          {
            /* avoid dangling else.  */
            i += 1;
            if ((a[i] < '0') || (a[i] > '9'))
              {
                ok = false;
              }
          }
        else
          {
            ok = false;
          }
      } while (! (! ok));
    }
}

extern "C" void NumberIO_ReadOct (unsigned int *x)
{
  typedef struct ReadOct__T10_a ReadOct__T10;

  struct ReadOct__T10_a { char array[MaxLineLength+1]; };
  ReadOct__T10 a;

  StrIO_ReadString ((char *) &a.array[0], MaxLineLength);
  NumberIO_StrToOct ((const char *) &a.array[0], MaxLineLength, x);
}

extern "C" void NumberIO_WriteOct (unsigned int x, unsigned int n)
{
  typedef struct WriteOct__T11_a WriteOct__T11;

  struct WriteOct__T11_a { char array[MaxLineLength+1]; };
  WriteOct__T11 a;

  NumberIO_OctToStr (x, n, (char *) &a.array[0], MaxLineLength);
  StrIO_WriteString ((const char *) &a.array[0], MaxLineLength);
}

extern "C" void NumberIO_OctToStr (unsigned int x, unsigned int n, char *a, unsigned int _a_high)
{
  typedef struct OctToStr__T12_a OctToStr__T12;

  struct OctToStr__T12_a { unsigned int array[MaxOctDigits-1+1]; };
  unsigned int i;
  unsigned int j;
  unsigned int Higha;
  OctToStr__T12 buf;

  i = 0;
  do {
    i += 1;
    if (i > MaxOctDigits)
      {
        StrIO_WriteString ((const char *) "NumberIO - increase MaxDigits", 29);
        StrIO_WriteLn ();
        M2RTS_HALT (-1);
        __builtin_unreachable ();
      }
    buf.array[i-1] = x % 8;
    x = x / 8;
  } while (! (x == 0));
  j = 0;
  Higha = _a_high;
  while ((n > i) && (j <= Higha))
    {
      a[j] = ' ';
      j += 1;
      n -= 1;
    }
  while ((i > 0) && (j <= Higha))
    {
      a[j] = ((char) (buf.array[i-1]+ ((unsigned int) ('0'))));
      j += 1;
      i -= 1;
    }
  if (j <= Higha)
    {
      a[j] = ASCII_nul;
    }
}

extern "C" void NumberIO_StrToOct (const char *a_, unsigned int _a_high, unsigned int *x)
{
  int i;
  char a[_a_high+1];

  /* make a local copy of each unbounded array.  */
  memcpy (a, a_, _a_high+1);

  NumberIO_StrToOctInt ((const char *) a, _a_high, &i);
  (*x) = (unsigned int ) (i);
}

extern "C" void NumberIO_ReadBin (unsigned int *x)
{
  typedef struct ReadBin__T13_a ReadBin__T13;

  struct ReadBin__T13_a { char array[MaxLineLength+1]; };
  ReadBin__T13 a;

  StrIO_ReadString ((char *) &a.array[0], MaxLineLength);
  NumberIO_StrToBin ((const char *) &a.array[0], MaxLineLength, x);
}

extern "C" void NumberIO_WriteBin (unsigned int x, unsigned int n)
{
  typedef struct WriteBin__T14_a WriteBin__T14;

  struct WriteBin__T14_a { char array[MaxLineLength+1]; };
  WriteBin__T14 a;

  NumberIO_BinToStr (x, n, (char *) &a.array[0], MaxLineLength);
  StrIO_WriteString ((const char *) &a.array[0], MaxLineLength);
}

extern "C" void NumberIO_BinToStr (unsigned int x, unsigned int n, char *a, unsigned int _a_high)
{
  typedef struct BinToStr__T15_a BinToStr__T15;

  struct BinToStr__T15_a { unsigned int array[MaxBits-1+1]; };
  unsigned int i;
  unsigned int j;
  unsigned int Higha;
  BinToStr__T15 buf;

  i = 0;
  do {
    i += 1;
    if (i > MaxBits)
      {
        StrIO_WriteString ((const char *) "NumberIO - increase MaxBits", 27);
        StrIO_WriteLn ();
        M2RTS_HALT (-1);
        __builtin_unreachable ();
      }
    buf.array[i-1] = x % 2;
    x = x / 2;
  } while (! (x == 0));
  j = 0;
  Higha = _a_high;
  while ((n > i) && (j <= Higha))
    {
      a[j] = ' ';
      j += 1;
      n -= 1;
    }
  while ((i > 0) && (j <= Higha))
    {
      a[j] = ((char) (buf.array[i-1]+ ((unsigned int) ('0'))));
      j += 1;
      i -= 1;
    }
  if (j <= Higha)
    {
      a[j] = ASCII_nul;
    }
}

extern "C" void NumberIO_StrToBin (const char *a_, unsigned int _a_high, unsigned int *x)
{
  int i;
  char a[_a_high+1];

  /* make a local copy of each unbounded array.  */
  memcpy (a, a_, _a_high+1);

  NumberIO_StrToBinInt ((const char *) a, _a_high, &i);
  (*x) = (unsigned int ) (i);
}

extern "C" void NumberIO_StrToBinInt (const char *a_, unsigned int _a_high, int *x)
{
  unsigned int i;
  bool ok;
  unsigned int higha;
  char a[_a_high+1];

  /* make a local copy of each unbounded array.  */
  memcpy (a, a_, _a_high+1);

  StrLib_StrRemoveWhitePrefix ((const char *) a, _a_high, (char *) a, _a_high);
  higha = StrLib_StrLen ((const char *) a, _a_high);
  i = 0;
  ok = true;
  while (ok)
    {
      if (i < higha)
        {
          if ((a[i] < '0') || (a[i] > '1'))
            {
              i += 1;
            }
          else
            {
              ok = false;
            }
        }
      else
        {
          ok = false;
        }
    }
  (*x) = 0;
  if (i < higha)
    {
      ok = true;
      do {
        (*x) = (2*(*x))+((int ) ( ((unsigned int) (a[i]))- ((unsigned int) ('0'))));
        if (i < higha)
          {
            /* avoid dangling else.  */
            i += 1;
            if ((a[i] < '0') || (a[i] > '1'))
              {
                ok = false;
              }
          }
        else
          {
            ok = false;
          }
      } while (! (! ok));
    }
}

extern "C" void NumberIO_StrToHexInt (const char *a_, unsigned int _a_high, int *x)
{
  unsigned int i;
  bool ok;
  unsigned int higha;
  char a[_a_high+1];

  /* make a local copy of each unbounded array.  */
  memcpy (a, a_, _a_high+1);

  StrLib_StrRemoveWhitePrefix ((const char *) a, _a_high, (char *) a, _a_high);
  higha = StrLib_StrLen ((const char *) a, _a_high);
  i = 0;
  ok = true;
  while (ok)
    {
      if (i < higha)
        {
          if (((a[i] >= '0') && (a[i] <= '9')) || ((a[i] >= 'A') && (a[i] <= 'F')))
            {
              ok = false;
            }
          else
            {
              i += 1;
            }
        }
      else
        {
          ok = false;
        }
    }
  (*x) = 0;
  if (i < higha)
    {
      ok = true;
      do {
        if ((a[i] >= '0') && (a[i] <= '9'))
          {
            (*x) = (0x010*(*x))+((int ) ( ((unsigned int) (a[i]))- ((unsigned int) ('0'))));
          }
        else if ((a[i] >= 'A') && (a[i] <= 'F'))
          {
            /* avoid dangling else.  */
            (*x) = (0x010*(*x))+((int ) (( ((unsigned int) (a[i]))- ((unsigned int) ('A')))+10));
          }
        if (i < higha)
          {
            /* avoid dangling else.  */
            i += 1;
            if (((a[i] < '0') || (a[i] > '9')) && ((a[i] < 'A') || (a[i] > 'F')))
              {
                ok = false;
              }
          }
        else
          {
            ok = false;
          }
      } while (! (! ok));
    }
}

extern "C" void NumberIO_StrToOctInt (const char *a_, unsigned int _a_high, int *x)
{
  unsigned int i;
  bool ok;
  unsigned int higha;
  char a[_a_high+1];

  /* make a local copy of each unbounded array.  */
  memcpy (a, a_, _a_high+1);

  StrLib_StrRemoveWhitePrefix ((const char *) a, _a_high, (char *) a, _a_high);
  higha = StrLib_StrLen ((const char *) a, _a_high);
  i = 0;
  ok = true;
  while (ok)
    {
      if (i < higha)
        {
          if ((a[i] < '0') || (a[i] > '7'))
            {
              i += 1;
            }
          else
            {
              ok = false;
            }
        }
      else
        {
          ok = false;
        }
    }
  (*x) = 0;
  if (i < higha)
    {
      ok = true;
      do {
        (*x) = (8*(*x))+((int ) ( ((unsigned int) (a[i]))- ((unsigned int) ('0'))));
        if (i < higha)
          {
            /* avoid dangling else.  */
            i += 1;
            if ((a[i] < '0') || (a[i] > '7'))
              {
                ok = false;
              }
          }
        else
          {
            ok = false;
          }
      } while (! (! ok));
    }
}

extern "C" void _M2_NumberIO_init (__attribute__((unused)) int argc,__attribute__((unused)) char *argv[],__attribute__((unused)) char *envp[])
{
}

extern "C" void _M2_NumberIO_fini (__attribute__((unused)) int argc,__attribute__((unused)) char *argv[],__attribute__((unused)) char *envp[])
{
}
